package com.icee.myth.server.stage;

import com.icee.myth.config.MapConfig;
import com.icee.myth.log.GameLogger;
import com.icee.myth.log.message.FileDebugGameLogMessage;
import com.icee.myth.log.message.GameLogMessage;
import com.icee.myth.log.message.builder.GameLogMessageBuilder;
import com.icee.myth.protobuf.ExternalCommonProtocol.StageBattleEnemyProto;
import com.icee.myth.protobuf.ExternalCommonProtocol.StageStateProto;
import com.icee.myth.protobuf.builder.ClientToMapBuilder;
import com.icee.myth.server.activity.stageActivity.StageActivityTemplates;
import com.icee.myth.server.actor.Human;
import com.icee.myth.server.battle.*;
import com.icee.myth.server.card.Card;
import com.icee.myth.server.card.CardFactories;
import com.icee.myth.server.card.CardStaticInfo;
import com.icee.myth.server.fighter.Fighter;
import com.icee.myth.server.sandbox.SandBox;
import com.icee.myth.server.social.BriefPlayerInfo;
import com.icee.myth.server.talent.TalentStaticInfo;
import com.icee.myth.server.talent.TalentsConfig;
import com.icee.myth.utils.Consts;
import com.icee.myth.utils.RandomGenerator;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * 关卡
 * @author liuxianke
 */
public class Stage {
    public final StageStaticInfo staticInfo;

    public final Human human;

    public int currentBattleIndex = 0;                // 当前战斗场号
    private final LinkedList<PveBattleSlotEnemy> currentBattleEnemies = new LinkedList<PveBattleSlotEnemy>();  // 当前战斗敌人

    public boolean isCurrentBattleExecuting = false;   // 为true表示正在计算战斗过程
    public boolean isCurrentBattleFinished = false;     // 当前战斗是否已胜利
    public boolean isStageFinished = false;             // 当前副本是否完成

    public boolean needRevive = false;  // 是否需要复活

    public final BriefPlayerInfo helperInfo;
    public StageBox box;        // 关卡掉落

    public Stage(Human human, StageStaticInfo staticInfo, BriefPlayerInfo helperInfo) {
        this.staticInfo = staticInfo;
        this.human = human;
        this.helperInfo = helperInfo;

        createBox();
        // 创建当前战斗敌人
        generateCurrentBattleEnemies();
    }

    public void moveNext() {
        assert (!isStageFinished);
        currentBattleIndex++;
        isCurrentBattleFinished = false;

        if (currentBattleIndex < staticInfo.battleIds.length) {
            generateCurrentBattleEnemies();
        } else {
            currentBattleEnemies.clear();
            isStageFinished = true;
        }
    }

    /**
     *  根据NPC的出场概率生成战斗NPCs
     */
    private void generateCurrentBattleEnemies() {
        currentBattleEnemies.clear();

        PveBattleStaticInfo battleStaticInfo = PveBattlesConfig.INSTANCE.getPveBattleStaticInfo(staticInfo.battleIds[currentBattleIndex]);

        // 产生敌人信息
        assert ((battleStaticInfo.battleEnemySlots != null) && (battleStaticInfo.battleEnemySlots.length <= 6));
        for (PveBattleSlotEnemyConfig enemyConfig : battleStaticInfo.battleEnemySlots) {
            if (enemyConfig != null) {
                assert ((enemyConfig.enemyPropabilitys != null) && (enemyConfig.enemyPropabilitys.length > 0));
                Random random = RandomGenerator.INSTANCE.generator;
                int tmp = random.nextInt(enemyConfig.enemyPropabilitys[enemyConfig.enemyPropabilitys.length-1].propabilityRange);
                for (PveBattleSlotEnemyPropability enemyPropability : enemyConfig.enemyPropabilitys) {
                    if (tmp < enemyPropability.propabilityRange) {
                        currentBattleEnemies.add(new PveBattleSlotEnemy(enemyConfig.slotId, enemyPropability.id, enemyPropability.realId, enemyPropability.level, enemyConfig.isBoss));
                        break;
                    }
                }
            }
        }
    }
    
    public StageStateProto buildStageStateProto() {
        StageStateProto.Builder builder1 = StageStateProto.newBuilder();

        builder1.setStageId(staticInfo.id);
        builder1.setStageType(staticInfo.type);
        
        if (currentBattleIndex != -1) {
            builder1.setCurrentBattleId(currentBattleIndex);

            for (PveBattleSlotEnemy enemy : currentBattleEnemies) {
                StageBattleEnemyProto.Builder builder2 = StageBattleEnemyProto.newBuilder();
                builder2.setSlotId(enemy.slotId);
                builder2.setCardId(enemy.cardId);
                builder2.setLevel(enemy.level);
                builder2.setIsBoss(enemy.isBoss);
                
                builder1.addCurrentBattleEnemies(builder2);
            }
        }
        
        builder1.setNeedRevive(needRevive);
        if (box != null) {
            builder1.setBox(box.buildRewardProto());
        }

        if (helperInfo != null) {
            builder1.setHelper(helperInfo.buildBriefPlayerProto(false, 0));
        }

        return builder1.build();
    }

    public PveBattle createPveBattle() {
        PveBattle pveBattle = new PveBattle(human.id, staticInfo.id, currentBattleIndex);
        SandBox sandBox = human.sandbox;
        
        // 取出队长卡片数据
        Card leaderCard = sandBox.slots[sandBox.leader];
        TalentStaticInfo leaderTalentStaticInfo = (leaderCard.staticInfo.leaderTalentId != -1)? TalentsConfig.INSTANCE.talentStaticInfos[leaderCard.staticInfo.leaderTalentId]:null;

        // 助战者天赋
        CardStaticInfo helperCardStaticInfo = null;
        TalentStaticInfo helperTalentStaticInfo = null;
        if (helperInfo != null) {
            helperCardStaticInfo = CardFactories.INSTANCE.getCardFactory(helperInfo.leaderCardId).staticInfo;

            if (helperCardStaticInfo.leaderTalentId != -1) {
                helperTalentStaticInfo = TalentsConfig.INSTANCE.talentStaticInfos[helperCardStaticInfo.leaderTalentId];
            }
        }

        float hpChange = (human.barrack != null)?1.0f+human.barrack.hpIncrease:1.0f;
        float atkChange = (human.ordnance != null)?1.0f+human.ordnance.atkIncrease:1.0f;
        int criAndTenChange = (human.council != null)?human.council.criAndTenIncrease:0;
        int hitAndDodChange = (human.training != null)?human.training.hitAndDodIncrease:0;
        // 加入玩家战士
        for (int i=0; i<6; i++) {
            Card card = sandBox.slots[i];
            if (card != null) {
                Fighter fighter = new Fighter(i, pveBattle, card.staticInfo, card.level, Long.MAX_VALUE, leaderTalentStaticInfo, helperTalentStaticInfo, false, 0, hpChange, atkChange, criAndTenChange, hitAndDodChange);
                pveBattle.addFighter(fighter);
            }
        }

        // 加入助战者
        if (helperInfo != null) {
            Fighter fighter = new Fighter(sandBox.helper, pveBattle, helperCardStaticInfo, helperInfo.leaderCardLevel, Long.MAX_VALUE, leaderTalentStaticInfo, helperTalentStaticInfo, false, 0, hpChange, atkChange, criAndTenChange, hitAndDodChange);
            pveBattle.addFighter(fighter);
        }

        // 加入敌人
        for (PveBattleSlotEnemy slotEnemy : currentBattleEnemies) {
            Fighter fighter = new Fighter(slotEnemy.slotId, pveBattle, CardFactories.INSTANCE.getCardFactory(slotEnemy.realCardId==0?slotEnemy.cardId:slotEnemy.realCardId).staticInfo, slotEnemy.level, Long.MAX_VALUE, null, null, slotEnemy.isBoss, StageActivityTemplates.INSTANCE.getStageCardDropMultiple(staticInfo.id), 1.0f, 1.0f, 0, 0);
            pveBattle.addFighter(fighter);

            if (slotEnemy.realCardId != 0) {
                pveBattle.addChangeCardInfo(new ChangeCardInfo(slotEnemy.slotId, slotEnemy.cardId, slotEnemy.realCardId));
            }
        }

        return pveBattle;
    }
    
    private StageBox createBox() {
        assert (box == null);
        // 创建宝箱
        box = new StageBox();
        StageRewardInfo rewardInfo = staticInfo.reward;
        if (rewardInfo != null) {
            Random random = RandomGenerator.INSTANCE.generator;

            box.experience = rewardInfo.experience;
            int silverRange = rewardInfo.maxSilver - rewardInfo.minSilver;
            box.silver = (silverRange > 0) ? rewardInfo.minSilver + random.nextInt(silverRange) : rewardInfo.minSilver;

            if ((rewardInfo.goldProbability > 0) && (rewardInfo.gold > 0)) {
                if (rewardInfo.goldProbability < 100) {
                    if (random.nextInt(100) < rewardInfo.goldProbability) {
                        box.gold = rewardInfo.gold;
                    } else {
                        box.gold = 0;
                    }
                } else {
                    box.gold = rewardInfo.gold;
                }
            }
        }

        return box;
    }

    public void revive() {
        if (needRevive) {
            // 计算复活价钱
            SandBox sandBox = human.sandbox;
            int totalRevivePrice = 0;
            for (int i=0; i<6; i++) {
                Card card = sandBox.slots[i];
                if (card != null) {
                    totalRevivePrice += card.staticInfo.soldPriceBase + card.staticInfo.soldPriceGrow * card.level;
                }
            }

            CardStaticInfo helperCardStaticInfo = null;
            if (helperInfo != null) {
                helperCardStaticInfo = CardFactories.INSTANCE.getCardFactory(helperInfo.leaderCardId).staticInfo;
                totalRevivePrice += helperCardStaticInfo.soldPriceBase + helperCardStaticInfo.soldPriceGrow * helperInfo.leaderCardLevel;
            }

            totalRevivePrice *= MapConfig.INSTANCE.reviveCardPriceRatio;

            if (human.getSilver() >= totalRevivePrice) {
                human.decreaseSilver(totalRevivePrice, Consts.SOUL_CHANGE_LOG_TYPE_REVIVE, staticInfo.battleIds[currentBattleIndex], true);

                needRevive = false;

                // 通知客户端复活成功
                human.sendMessage(ClientToMapBuilder.buildStageRevived());

                // 记录行为日志

                if (MapConfig.INSTANCE.useCYLog == true) {
                    List<String> cyLogList = new ArrayList<String>();
                    cyLogList.add("behaviorMC");
                    cyLogList.add(String.valueOf(MapConfig.INSTANCE.gameId));
                    cyLogList.add("KDTY");
                    cyLogList.add(String.valueOf(human.id));
                    cyLogList.add(human.name);
                    cyLogList.add("");
                    cyLogList.add("StageRevivedDBBehavior");
                    cyLogList.add(staticInfo.type + " " + staticInfo.id + " " + totalRevivePrice);
                    cyLogList.add("");
                    cyLogList.add("");
                    cyLogList.add("");
                    cyLogList.add("");
                    cyLogList.add("");
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileCYGameLogMessage(cyLogList, GameLogMessage.GameLogType.GAMELOGTYPE_CY_BEHAVIOR));
                }
                GameLogger.getlogger().log(GameLogMessageBuilder.buildStageRevivedDBBehaviorGameLogMessage(human.id, staticInfo.type, staticInfo.id, totalRevivePrice));
            } else {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Player[" + human.id + "] can't revive stage because not enough silver:" + totalRevivePrice + "."));
            }
        } else {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                    "Player[" + human.id + "] can't revive stage because not dead."));
        }
    }
}
